package com.lib.utils;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.InputStreamReader;
import java.util.List;

/**
 * <pre>
 *     author: Blankj
 *     blog  : http://blankj.com
 *     time  : 2016/8/7
 *     desc  : Shell相关工具类
 * </pre>
 */
public class ShellUtils {

	private ShellUtils() {

		throw new UnsupportedOperationException("u can't instantiate me...");
	}

	/**
	 * 是否是在root下执行命令
	 *
	 * @param command
	 * 	命令
	 * @param isRoot
	 * 	是否需要root权限执行
	 *
	 * @return CommandResult
	 */
	public static CommandResult execCmd(String command, boolean isRoot) {

		return execCmd(new String[]{command}, isRoot, true);
	}

	/**
	 * 是否是在root下执行命令
	 *
	 * @param commands
	 * 	多条命令链表
	 * @param isRoot
	 * 	是否需要root权限执行
	 *
	 * @return CommandResult
	 */
	public static CommandResult execCmd(List<String> commands, boolean isRoot) {

		return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRoot, true);
	}

	/**
	 * 是否是在root下执行命令
	 *
	 * @param commands
	 * 	多条命令数组
	 * @param isRoot
	 * 	是否需要root权限执行
	 *
	 * @return CommandResult
	 */
	public static CommandResult execCmd(String[] commands, boolean isRoot) {

		return execCmd(commands, isRoot, true);
	}

	/**
	 * 是否是在root下执行命令
	 *
	 * @param command
	 * 	命令
	 * @param isRoot
	 * 	是否需要root权限执行
	 * @param isNeedResultMsg
	 * 	是否需要结果消息
	 *
	 * @return CommandResult
	 */
	public static CommandResult execCmd(String command, boolean isRoot, boolean isNeedResultMsg) {

		return execCmd(new String[]{command}, isRoot, isNeedResultMsg);
	}

	/**
	 * 是否是在root下执行命令
	 *
	 * @param commands
	 * 	命令链表
	 * @param isRoot
	 * 	是否需要root权限执行
	 * @param isNeedResultMsg
	 * 	是否需要结果消息
	 *
	 * @return CommandResult
	 */
	public static CommandResult execCmd(List<String> commands, boolean isRoot, boolean isNeedResultMsg) {

		return execCmd(commands == null ? null : commands.toArray(new String[]{}), isRoot, isNeedResultMsg);
	}

	/**
	 * 是否是在root下执行命令
	 *
	 * @param commands
	 * 	命令数组
	 * @param isRoot
	 * 	是否需要root权限执行
	 * @param isNeedResultMsg
	 * 	是否需要结果消息
	 *
	 * @return CommandResult
	 */
	public static CommandResult execCmd(String[] commands, boolean isRoot, boolean isNeedResultMsg) {

		int result = -1;
		if (commands == null || commands.length == 0) {
			return new CommandResult(result, null, null);
		}
		Process process = null;
		BufferedReader successResult = null;
		BufferedReader errorResult = null;
		StringBuilder successMsg = null;
		StringBuilder errorMsg = null;
		DataOutputStream os = null;
		try {
			process = Runtime.getRuntime().exec(isRoot ? "su" : "sh");
			os = new DataOutputStream(process.getOutputStream());
			for (String command : commands) {
				if (command == null)
					continue;
				os.write(command.getBytes());
				os.writeBytes("\n");
				os.flush();
			}
			os.writeBytes("exit\n");
			os.flush();
			result = process.waitFor();
			if (isNeedResultMsg) {
				successMsg = new StringBuilder();
				errorMsg = new StringBuilder();
				successResult = new BufferedReader(new InputStreamReader(process.getInputStream()));
				errorResult = new BufferedReader(new InputStreamReader(process.getErrorStream()));
				String s;
				while ((s = successResult.readLine()) != null) {
					successMsg.append(s);
				}
				while ((s = errorResult.readLine()) != null) {
					errorMsg.append(s);
				}
			}
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			CloseUtils.close(os, successResult, errorResult);
			if (process != null) {
				process.destroy();
			}
		}
		return new CommandResult(
			result,
			successMsg == null ? null : successMsg.toString(),
			errorMsg == null ? null : errorMsg.toString()
		);
	}

	/**
	 * 返回的命令结果
	 */
	public static class CommandResult {

		/**
		 * 结果码
		 **/
		public int result;

		/**
		 * 成功信息
		 **/
		public String successMsg;

		/**
		 * 错误信息
		 **/
		public String errorMsg;

		public CommandResult(int result, String successMsg, String errorMsg) {

			this.result = result;
			this.successMsg = successMsg;
			this.errorMsg = errorMsg;
		}
	}
}